package app

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"me.com/onePass/internal/config"
	"me.com/onePass/internal/database"
	"me.com/onePass/pkg/health"
)

// App 主应用程序
type App struct {
	config    *config.Config
	dbClient  *database.PostgresClient
	server    *http.Server
}

// NewApp 创建应用程序实例
func NewApp(cfg *config.Config) *App {
	return &App{
		config: cfg,
	}
}

// Initialize 初始化应用程序组件
func (a *App) Initialize() error {
	log.Println("正在初始化应用程序...")

	// 初始化数据库连接
	if err := a.initDatabase(); err != nil {
		return fmt.Errorf("failed to initialize database: %w", err)
	}

	// 初始化HTTP服务器
	a.initHTTPServer()

	log.Println("应用程序初始化完成")
	return nil
}

// initDatabase 初始化数据库连接
func (a *App) initDatabase() error {
	if a.config.Database.Postgres.Host != "" {
		client, err := database.NewPostgresClient(a.config)
		if err != nil {
			return err
		}
		a.dbClient = client

		// 测试数据库连接
		info, err := client.TestConnection()
		if err != nil {
			return err
		}
		log.Println(info)
	}
	return nil
}

// initHTTPServer 初始化HTTP服务器
func (a *App) initHTTPServer() {
	// 创建健康检查处理器
	healthHandler := health.NewHealthHandler(a.dbClient, a.config.App.Version)

	// 设置路由
	mux := http.NewServeMux()
	mux.Handle("/health", healthHandler)
	mux.HandleFunc("/live", health.LiveHandler)
	mux.HandleFunc("/ready", healthHandler.ReadyHandler)
	mux.HandleFunc("/", a.rootHandler)

	// 创建HTTP服务器
	a.server = &http.Server{
		Addr:         fmt.Sprintf(":%d", a.config.Server.Port),
		Handler:      mux,
		ReadTimeout:  parseDuration(a.config.Server.ReadTimeout, 30*time.Second),
		WriteTimeout: parseDuration(a.config.Server.WriteTimeout, 30*time.Second),
		IdleTimeout:  parseDuration(a.config.Server.IdleTimeout, 60*time.Second),
	}
}

// rootHandler 根路径处理器
func (a *App) rootHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	jsonResponse := map[string]interface{}{
		"app":        a.config.App.Name,
		"version":    a.config.App.Version,
		"status":     "running",
		"timestamp":  time.Now().Format(time.RFC3339),
		"endpoints": map[string]string{
			"health": "/health",
			"live":   "/live",
			"ready":  "/ready",
		},
	}

	if err := json.NewEncoder(w).Encode(jsonResponse); err != nil {
		http.Error(w, "Failed to encode response", http.StatusInternalServerError)
	}
}

// Run 启动应用程序
func (a *App) Run() error {
	// 启动HTTP服务器
	go func() {
		log.Printf("HTTP服务器启动在端口 %d", a.config.Server.Port)
		if err := a.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("HTTP服务器启动失败: %v", err)
		}
	}()

	// 等待中断信号
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	log.Println("正在关闭应用程序...")
	return a.Shutdown()
}

// Shutdown 优雅关闭应用程序
func (a *App) Shutdown() error {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// 关闭HTTP服务器
	if err := a.server.Shutdown(ctx); err != nil {
		return fmt.Errorf("HTTP服务器关闭失败: %w", err)
	}

	// 关闭数据库连接
	if a.dbClient != nil {
		a.dbClient.Close()
	}

	log.Println("应用程序已安全关闭")
	return nil
}

// parseDuration 解析持续时间字符串，提供默认值
func parseDuration(durationStr string, defaultValue time.Duration) time.Duration {
	if durationStr == "" {
		return defaultValue
	}
	duration, err := time.ParseDuration(durationStr)
	if err != nil {
		log.Printf("警告: 无法解析持续时间 '%s', 使用默认值 %v", durationStr, defaultValue)
		return defaultValue
	}
	return duration
}